package com.hx.util.md5;

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * 实现DES加密和解密的过程
 * @author Liudong
 */
public class DESCipher {

    private final static String DES = "DES";

    /**
     * 加密
     * @param src   数据源
     * @param key  密钥，长度必须是8的倍数
     * @return         返回加密后的数据
     * @throws Exception
     */
    public static byte[] encrypt(byte[] src, byte[] key)
            throws Exception {
        //DES算法要求有一个可信任的随机数源
        SecureRandom sr = new SecureRandom();
        // 从原始密匙数据创建DESKeySpec对象
        DESKeySpec dks = new DESKeySpec(key);
        // 创建一个密匙工厂，然后用它把DESKeySpec转换成
        // 一个SecretKey对象
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
        SecretKey securekey = keyFactory.generateSecret(dks);
        // Cipher对象实际完成加密操作
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        // 用密匙初始化Cipher对象
        cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
        // 现在，获取数据并加密
        // 正式执行加密操作
        return cipher.doFinal(src);
    }

    /**
     * 加密
     * @param src   数据源
     * @return         返回加密后的数据
     * @throws Exception
     */
    public static String encrypt(String src)
            throws Exception {
        byte[] mKey = {(byte) 60, (byte) 164, (byte) 119, (byte) 229, (byte) 131, (byte) 122, (byte) 34, (byte) 198, (byte) 253, (byte) 52, (byte) 0, (byte) 202, (byte) 26, (byte) 117, (byte) 42, (byte) 222, (byte) 88, (byte) 167, (byte) 40, (byte) 212, (byte) 163, (byte) 98, (byte) 237, (byte) 157};
        byte[] mIV = {(byte) 171, (byte) 59, (byte) 240, (byte) 233, (byte) 64, (byte) 96, (byte) 45, (byte) 94};
        //byte[] SaltByteArray = {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76};
        DaoSecureRandom sr = new DaoSecureRandom();
        SecretKey key = new SecretKeySpec(mKey, "DESede");
        IvParameterSpec iv = new IvParameterSpec(mIV);
        Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, iv, sr);
        return (new sun.misc.BASE64Encoder()).encode(cipher.doFinal(src.getBytes()));
    }

    /**
     * 解密
     * @param src    数据源
     * @param key    密钥，长度必须是8的倍数
     * @return    返回解密后的原始数据
     * @throws Exception
     */
    public static byte[] decrypt(byte[] src, byte[] key)
            throws Exception {
        if (src == null) {
            return null;
        }
        //DES算法要求有一个可信任的随机数源
        SecureRandom sr = new SecureRandom();
        // 从原始密匙数据创建一个DESKeySpec对象
        DESKeySpec dks = new DESKeySpec(key);
        // 创建一个密匙工厂，然后用它把DESKeySpec对象转换成
        // 一个SecretKey对象
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
        SecretKey securekey = keyFactory.generateSecret(dks);
        // Cipher对象实际完成解密操作
        Cipher cipher = Cipher.getInstance(DES);
        // 用密匙初始化Cipher对象
        cipher.init(Cipher.DECRYPT_MODE, securekey);
        // 现在，获取数据并解密
        // 正式执行解密操作
        return cipher.doFinal(src);
    }

    /**
     * 将给定的已加密的数据通过指定的密钥进行解密
     * @param key  密钥
     * @param raw  待解密的数据
     * @return   byte[] 解密后的数据
     * @throws util.EncryptException
     */
    public static byte[] doDecrypt(byte[] key, byte[] raw) throws Exception {
        try {


            DESKeySpec dks = new DESKeySpec(key);

            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
            SecretKey securekey = keyFactory.generateSecret(dks);
            Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            // Decrypt
            cipher.init(Cipher.DECRYPT_MODE, securekey);
            //  BASE64Decoder decoder = new BASE64Decoder();
            //  byte[] data64 = decoder.decodeBuffer(raw);
            byte[] data = cipher.doFinal(raw);
            //String result = new String(stringBytes, "UTF8");
            //System.out.println("the decrypted data is: " + result);
            return data;
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("Do decrypt occurs Exception.[" + e.getMessage() + "]");
        }
    }

    /**
     * 二进制转字符串
     * @param b
     * @return
     */
    public static String byte2hex(byte[] b) {
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++) {
            stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
            if (stmp.length() == 1) {
                hs = hs + "0" + stmp;
            } else {
                hs = hs + stmp;
            }
            if (n < b.length - 1) {
                hs = hs;
            }
        }
        return hs.toUpperCase();
    }

    /**
     * 解密时转换成byte算法时补位
     * @param strhex 传入的字串符
     * @return byte
     * 编写:yaojs
     * 日期:2006.12.13
     */
    public static byte[] hex2byte(String strhex) {
        if (strhex == null) {
            return null;
        }
        int l = strhex.length();
        if (l % 2 == 1) {
            return null;
        }

        byte[] b = new byte[l / 2];

        for (int i = 0; i != l / 2; i++) {

            b[i] = (byte) Integer.parseInt(strhex.substring(i * 2, i * 2 + 2), 16);
        }
        return b;
    }

    /**
     * 测试入口
     * @param args
     */
    public static void main(String[] args) throws Exception {

        System.out.print(encrypt("123456"));

//        String privateKey = "userKey8";
//        String sourceWord = "6C-F0-49-B3-60-F0,127.0.0.1";
//
//        byte[] des = encrypt(sourceWord.getBytes(), privateKey.getBytes()); //加密数据
//        String t = byte2hex(des);
//        System.out.println(byte2hex(des)); //输出数据
////        BASE64Encoder base64Eecode = new BASE64Encoder();
////        String base64EValue = base64Eecode.encodeBuffer(byte2hex(des).getBytes()); //将加密后的数据BCD码，然后再BASE64
////        System.out.println(base64EValue); 
////        //base64EValue就是传输过来的内容
////        //String desString = "YFZzbfqaRWOTAWbJpKLxuMGpE/Fc+M8xdQTpdu2RwsQ=";
////        BASE64Decoder base64Decode = new BASE64Decoder();    
////        byte[] base64DValue = base64Decode.decodeBuffer(desString);  //将传输过来的内容BASE64解码 
//        //byte[] bValue = hex2byte(new String(base64DValue)); //bcd补位解码
//        byte[] undes = decrypt(hex2byte(t), privateKey.getBytes()); //解密数据
//
//        System.out.println(hex2byte(t));
//        System.out.println("=++++" + hex2byte("5B5AC429D5BC62F77830F4F84430C2AF68C9501CAEA44BBB36E4E021E23CC422"));
//
//        System.out.println(new String(undes)); //输出解密数据
    }
}
